package com.mallcai.bigdata.ladon.service.report.impl;

import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.CreateCache;
import com.mallcai.bigdata.ladon.dpl.entity.common.Datasource;
import com.mallcai.bigdata.ladon.dpl.entity.report.QueryField;
import com.mallcai.bigdata.ladon.dpl.entity.report.Report;
import com.mallcai.bigdata.ladon.dpl.entity.report.ReportColumn;
import com.mallcai.bigdata.ladon.dpl.entity.report.ReportSql;
import com.mallcai.bigdata.ladon.service.common.IDatasourceService;
import com.mallcai.bigdata.ladon.service.report.IReportObjectQueryService;
import com.mallcai.bigdata.ladon.service.report.IReportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * @author feixy
 * @version 1.0
 * @date 2019-09-03 16:10
 */
@Service
@Slf4j
public class ReportObjectQueryService implements IReportObjectQueryService {

    @Autowired
    private IDatasourceService iDatasourceService;

    @Autowired
    private IReportService iReportService;

    @CreateCache(name = "report.meta-", cacheType = CacheType.REMOTE, expire = 1, timeUnit = TimeUnit.HOURS)
    private Cache<String, Object> metaCache;


    @Override
    public Report getReportByCode(String reportCode) {
        String key = String.format("%s-%s", MetaRefreshType.REPORT.getCode(),reportCode);
        return get(key, ()->iReportService.getReportByCode(reportCode)).map(item-> ((Report) item)).orElse(null);
    }

    @Override
    public ReportSql getReportSqlById(Long sqlId) {
        String key = String.format("%s-%s",MetaRefreshType.SQL.getCode(),sqlId);
        return get(key, ()->iReportService.getReportSqlById(sqlId)).map(item-> ((ReportSql) item)).orElse(null);
    }

    @Override
    public Datasource getDatasourceById(Long dsId) {
       String key = String.format("%s-%s",MetaRefreshType.DATA_SOURCE.getCode(),dsId);
       return get(key, ()->iDatasourceService.getById(dsId)).map(item-> ((Datasource) item)).orElse(null);
    }

    @Override
    public List<ReportColumn> listColumnByReportId(Long reportId) {
        String key = String.format("%s-%s",MetaRefreshType.COLUMNS.getCode(),reportId);
        return get(key, ()->iReportService.listColumnByReportId(reportId)).map(item-> ((List<ReportColumn>) item)).orElse(null);
    }

    @Override
    public List<QueryField> listQueryFieldByReportId(Long reportId) {
        String key = String.format("%s-%s", MetaRefreshType.FIELDS.getCode(), reportId);
        return get(key, ()->iReportService.listQueryFieldByReportId(reportId)).map(item-> ((List<QueryField>) item)).orElse(null);
    }

    private Optional<Object> get(String key, Supplier<Object> loader){
      return Optional.ofNullable(metaCache.computeIfAbsent(key, k->{
          log.info("key:{},缓存中没有对应的记录,从数据库中加载元数据", k);
          return loader.get();
      }));
    }

    @Override
    public void evictMetaCache(MetaRefreshEvent event){
        metaCache.remove(event.getCacheKey());
    }
}
